﻿using AMS.Services.DomainModels;
using Microsoft.Extensions.Options;
using OA.Infrastructure.Abstractions;
using OA.Infrastructure.DomainModels;
using OA.Infrastructure.DomainModels.Callback;
using OA.Infrastructure.DomainModels.TemporaryAuthorization;
using OA.Infrastructure.WeCom;
using OA.Infrastructure.WeCom.Abstractions;

namespace AMS.Services.EventHandlers;

internal class WeComTemplateCardEventHandler : IWeComCallbackEventHandler<WeComTemplateCardEvent>
{
    private readonly IApprovalService _approvalService;
    private readonly IWeComService _weComService;
    private readonly IServiceProvider _serviceProvider;
    private readonly DbContext _context;
    private readonly WeComOptions _options;

    public WeComTemplateCardEventHandler(
        IApprovalService approvalService,
        IServiceProvider serviceProvider,
        IWeComService weComService,
        DbContext context,
        IOptions<WeComOptions> options)
    {
        _approvalService = approvalService;
        _weComService = weComService;
        _serviceProvider = serviceProvider;
        _context = context;
        _options = options.Value;
    }

    public async Task<OperationalResult> HandleAsync(WeComTemplateCardEvent args, CancellationToken cancellationToken = default)
    {
        var job = await _context.Set<ScheduleJob>().FirstOrDefaultAsync(x => x.JobId == args.TaskId, cancellationToken);

        try
        {
            if (job is not null)
            {
                var result = args.EventKey switch
                {
                    WeComCallbackEvents.TemplateCardApprovePassEventKey => await _approvalService.PassAsync(int.Parse(job.Key), cancellationToken),
                    WeComCallbackEvents.TemplateCardApproveRejectEventKey => await _approvalService.RejectAsync(int.Parse(job.Key), string.Empty, cancellationToken),
                    WeComCallbackEvents.TemplateCardApproveNoticeSelfEventKey => throw new NotImplementedException(),
                    WeComCallbackEvents.TemplateCardUserTemporaryAuthGrantEventKey => await UserTemporaryAuthorizationGrantAsync(job.Key, cancellationToken),
                    WeComCallbackEvents.TemplateCardUserTemporaryAuthRejectEventKey => await UserTemporaryAuthorizationRejectAsync(job.Key, cancellationToken),
                    WeComCallbackEvents.TemplateCardPermissionTemporaryAuthGrantEventKey => await PermissionTemporaryAuthorizationGrantAsync(job.Key, cancellationToken),
                    WeComCallbackEvents.TemplateCardPermissionTemporaryAuthRejectEventKey => await PermissionTemporaryAuthorizationRejectAsync(job.Key, cancellationToken),
                    _ => throw new NotImplementedException(),
                };

                if (result.EnsureSucceed())
                {
                    await _weComService.UpdateSampleTemplateCardAsync(new WeComTemplateCardSampleUpdate
                    {
                        AgentId = _options.AgentId,
                        Response_code = args.ResponseCode,
                        Button = new WeComTemplateCardButtonUpdate
                        {
                            Replace_name = args.EventKey switch
                            {
                                WeComCallbackEvents.TemplateCardApprovePassEventKey => "已通过",
                                WeComCallbackEvents.TemplateCardApproveRejectEventKey => "已驳回",
                                WeComCallbackEvents.TemplateCardUserTemporaryAuthGrantEventKey => "已授权",
                                WeComCallbackEvents.TemplateCardUserTemporaryAuthRejectEventKey => "已驳回",
                                WeComCallbackEvents.TemplateCardPermissionTemporaryAuthGrantEventKey => "已授权",
                                WeComCallbackEvents.TemplateCardPermissionTemporaryAuthRejectEventKey => "已驳回",
                                _ => throw new NotImplementedException(),
                            }
                        },
                        AtAll = 1
                    });

                    job.Status = OA.Infrastructure.Enums.JobStatus.Closed;
                    _context.Set<ScheduleJob>().Update(job);

                    await _context.SaveChangesAsync(cancellationToken);
                }
                else
                {
                    throw new InvalidTemplateCardException();
                }

                return result;
            }
            else
            {
                throw new InvalidTemplateCardException();
            }
        }
        catch (InvalidTemplateCardException)
        {
            await _weComService.UpdateSampleTemplateCardAsync(new WeComTemplateCardSampleUpdate
            {
                AgentId = _options.AgentId,
                Response_code = args.ResponseCode,
                Button = new WeComTemplateCardButtonUpdate
                {
                    Replace_name = args.EventKey switch
                    {
                        _ => "已失效",
                    }
                },
                AtAll = 1
            });
        }

        return OperationalResult.Fail();
    }

    private async Task<OperationalResult> UserTemporaryAuthorizationGrantAsync(string key, CancellationToken cancellationToken = default)
    {
        var service = _serviceProvider.GetRequiredService<ITemporaryAuthorizationService<TemporaryAuthorizationCodeModel>>();

        return await service.GrantAsync(key, cancellationToken);
    }

    private async Task<OperationalResult> UserTemporaryAuthorizationRejectAsync(string key, CancellationToken cancellationToken = default)
    {
        var service = _serviceProvider.GetRequiredService<ITemporaryAuthorizationService<TemporaryAuthorizationCodeModel>>();

        return await service.RejectAsync(key, cancellationToken);
    }

    private async Task<OperationalResult> PermissionTemporaryAuthorizationGrantAsync(string key, CancellationToken cancellationToken = default)
    {
        var service = _serviceProvider.GetRequiredService<ITemporaryAuthorizationService<TemporaryAuthorizationPermissionModel>>();

        return await service.GrantAsync(key, cancellationToken);
    }

    private async Task<OperationalResult> PermissionTemporaryAuthorizationRejectAsync(string key, CancellationToken cancellationToken = default)
    {
        var service = _serviceProvider.GetRequiredService<ITemporaryAuthorizationService<TemporaryAuthorizationPermissionModel>>();

        return await service.RejectAsync(key, cancellationToken);
    }
}